package com.example.controller;

import com.example.entity.User;
import com.example.entity.example.UserExample;
import com.example.security.SecurityUser;
import com.example.service.StudentService;
import com.example.service.TeacherService;
import com.example.service.UserService;
import com.example.util.CustomConstant;
import com.example.util.CustomUtil;
import com.example.util.RedisUtil;
import com.example.util.ResultEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.List;


@RequestMapping("/user")
@Controller
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    StudentService studentService;

    @Autowired
    TeacherService teacherService;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    BCryptPasswordEncoder passwordEncoder;

    @ResponseBody
    @RequestMapping("/do/register")
    public ResultEntity<Object> doRegister(@RequestParam("name") String name,
                                           @RequestParam("phone") String phone,
                                           @RequestParam("code") String code,
                                           @RequestParam("password") String password
    ) {
        String key = CustomConstant.REDIS_VERIFY_CODE_PREFIX + phone;
        Object value = redisUtil.get(key);
        if (value == null || !value.toString().equals(code)) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_VERIFY_CODE_INVALID);
        }
        redisUtil.del(key);
        if (userService.getByIdOrPhone(phone) != null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_PHONE_ALREADY_EXISTS);
        }

        // 创建user
        User user = new User();
        user.setRole("普通用户");
        user.setName(name);
        user.setPhone(phone);
        // 密码加密
        String encodePassword = passwordEncoder.encode(password);
        user.setPassword(encodePassword);
        userService.add(user);
        return ResultEntity.successWithoutData();
    }

    @PreAuthorize("hasRole('ROLE_管理员')")
    @ResponseBody
    @RequestMapping("/get.json")
    public ResultEntity<List<User>> get(@RequestParam("page") Integer page,
                                        @RequestParam("limit") Integer limit,
                                        @RequestParam(value = "id", required = false) Integer id,
                                        @RequestParam(value = "name", required = false) String name,
                                        @RequestParam(value = "phone", required = false) String phone,
                                        @RequestParam(value = "role", required = false) String role

    ) {
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        if (id != null) {
            criteria.andIdEqualTo(id);
        }
        if (name != null && !name.isEmpty()) {
            name = '%' + name + '%';
            criteria.andNameLike(name);
        }
        if (phone != null && !phone.isEmpty()) {
            phone = '%' + phone + '%';
            criteria.andPhoneLike(phone);
        }
        if (role != null && !role.isEmpty()) {
            criteria.andRoleEqualTo(role);
        }
        List<User> users = userService.getByExampleWithLimit(example, page, limit);
        long count = userService.getCountByExample(example);
        return ResultEntity.createResultEntity(0, null, count, users);
    }

    @PreAuthorize("hasRole('ROLE_管理员')")
    @RequestMapping("/add/page.html")
    public String addPage() {
        return "user/user-add";
    }

    @PreAuthorize("hasRole('ROLE_管理员')")
    @ResponseBody
    @RequestMapping("/add")
    public ResultEntity<Object> add(@RequestBody User user) {
        // 密码加密
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        userService.add(user);
        return ResultEntity.successWithoutData();
    }

    /**
     * 前往用户修改页面
     */
    @RequestMapping("/modify/page.html")
    public String modifyPageWithoutId(ModelMap modelMap, HttpSession session) {
        User user = CustomUtil.getCurrentUser(session).getOriginalUser();
        modelMap.addAttribute("user", user);
        return "user/user-modify";
    }

    @PreAuthorize("hasRole('ROLE_管理员')")
    @RequestMapping("/{id}/modify/page.html")
    public String modifyPage(ModelMap modelMap, @PathVariable("id") Integer id) {
        User user = userService.getById(id);
        modelMap.addAttribute("user", user);
        return "user/user-modify";
    }

    @ResponseBody
    @RequestMapping("/update")
    public ResultEntity<Object> update(@RequestBody User user, HttpSession session) {
        User me = CustomUtil.getCurrentUser(session).getOriginalUser();
        if (!"管理员".equals(me.getRole()) && !me.getId().equals(user.getId())) {
            // 没有管理员权限不能修改其他用户信息
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_ACCESS_DENIED);
        }
        String password = user.getPassword();
        if (password != null && !password.isEmpty()) {
            // 密码加密
            String encodePassword = passwordEncoder.encode(password);
            user.setPassword(encodePassword);
        } else {
            user.setPassword(null);
        }
        userService.updateSelectiveById(user);
        return ResultEntity.successWithoutData();
    }

    @PreAuthorize("hasRole('ROLE_管理员')")
    @ResponseBody
    @RequestMapping("/remove")
    public ResultEntity<Object> remove(@RequestParam("id") Integer id) {
        userService.removeById(id);
        return ResultEntity.successWithoutData();
    }

    @ResponseBody
    @RequestMapping("/bind/teacher")
    public ResultEntity<Object> bindTeacher(@RequestParam("id") String id, HttpSession session) {
        SecurityUser securityUser = CustomUtil.getCurrentUser(session);
        User user = securityUser.getOriginalUser();
        Integer userId = user.getId();
        if (userService.judgeBind(userId)) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_ID_ALREADY_BIND);
        }
        if (teacherService.getById(id) == null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_ID_NOT_EXISTS);
        }
        if (userService.getByTeacherId(id) != null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_ID_ALREADY_BIND2);
        }
        userService.bindTeacher(userId, id);
        user.setRole("教师");
        userService.updateSelectiveById(user);
        return ResultEntity.successWithoutData();
    }

    @ResponseBody
    @RequestMapping("/bind/student")
    public ResultEntity<Object> bindStudent(@RequestParam("id") String id, HttpSession session) {
        SecurityUser securityUser = CustomUtil.getCurrentUser(session);
        User user = securityUser.getOriginalUser();
        Integer userId = user.getId();
        if (userService.judgeBind(userId)) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_ID_ALREADY_BIND);
        }
        if (studentService.getById(id) == null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_ID_NOT_EXISTS);
        }
        if (userService.getByStudentId(id) != null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_ID_ALREADY_BIND2);
        }
        userService.bindStudent(userId, id);
        user.setRole("学生");
        userService.updateSelectiveById(user);
        return ResultEntity.successWithoutData();
    }

    @ResponseBody
    @RequestMapping("/forget/password")
    public ResultEntity<Object> forgetPassword(@RequestParam("phone") String phone,
                                               @RequestParam("verifyCode") String verifyCode,
                                               @RequestParam("password") String password) {
        User user = userService.getByIdOrPhone(phone);
        if (user == null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_PHONE_UNREGISTERED);
        }

        String key = CustomConstant.REDIS_VERIFY_CODE_PREFIX + phone;
        Object value = redisUtil.get(key);
        if (value == null || !value.toString().equals(verifyCode)) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_VERIFY_CODE_INVALID);
        }
        redisUtil.del(key);
        if (userService.getByIdOrPhone(phone) == null) {
            return ResultEntity.failedWithoutData(CustomConstant.MESSAGE_THE_PHONE_UNREGISTERED);
        }

        // 密码加密
        String encodePassword = passwordEncoder.encode(password);
        user.setPassword(encodePassword);
        userService.updateSelectiveById(user);
        return ResultEntity.successWithoutData();
    }
}
